#include "test_mgr.h"
#include <sys/time.h>
#include "math.h"
#include "signal.h"
#include <string.h>
#include "role.h"
#include <unistd.h>

#define CLIENT_NUM 1
#define MSG_TOTAL 10000

test_mgr* test_mgr::instance_ = nullptr;

static long get_ms_time() {
    struct timeval tv;
    memset(&tv, 0x00, sizeof(tv));

    gettimeofday(&tv, nullptr);
    return tv.tv_sec * 1000 + tv.tv_usec / 1000;
}

static std::string get_str_time() {
    char buf[80] = {0};
    struct tm* tm_info;
    time_t now = time(nullptr);

    tm_info = localtime(&now);
    strftime(buf, sizeof(buf), "%Y%02m%02d %H:%M:%S", tm_info);

    return buf;
}

test_mgr::test_mgr(): 
    client_num_(CLIENT_NUM), login_success_(0),
    msg_total_(MSG_TOTAL), msg_send_(0), send_start_(0), 
    send_end_(0), msg_recv_(0), recv_cost_(0), QPS_(0) {
    this->loop_ = uv_default_loop();

    memset(&this->login_timer_, 0x00, sizeof(uv_timer_t));
    this->login_timer_.data = this;
}

int test_mgr::msg_per_robot() const {
    return ceil(this->msg_total_ * 1.0 / this->client_num_);
}

void test_mgr::set_send_end() {
    this->send_end_= get_ms_time();
}

void test_mgr::add_msg_send_count() {
    ++this->msg_send_;

    if (this->msg_send_ < this->msg_total_) return;

    this->set_send_end();
}

void test_mgr::add_msg_recv_count() {
    ++this->msg_recv_;

    if (this->msg_recv_ < this->msg_total_) return;

    printf("all receiving action finish\n");

    this->QPS_ = (this->msg_send_ * 1000.0) / (get_ms_time() - this->send_start_);
    auto it = roles_.begin();
    while (it != roles_.end()) {
        role * r = *it;
        it = roles_.erase(it);
        delete r;
        r = nullptr;
    }

    exit(0);
}

void test_mgr::add_msg_recv_cost(long time_cost) {
    this->recv_cost_ += time_cost;
}

void test_mgr::start_login() {
    int ret = uv_timer_init(loop_, &login_timer_);
    if (ret != 0) {
        printf("login timer init error:%s", uv_err_name(ret));
        return;
    }

    ret = uv_timer_start(&login_timer_, &test_mgr::on_login_timeout, 10, 10);
    if (ret != 0) {
        printf("login timer start error:%s", uv_err_name(ret));
        return;
    }
}

void test_mgr::on_login_timeout(uv_timer_t* handle) {
    test_mgr* tm = static_cast<test_mgr*>(handle->data);

    if (&tm->login_timer_ != handle) {
        printf("unknow error");
        return;
    }

    static int index = 0;

    if (index < tm->client_num_) {
        role* r = new role(tm->loop_);
        tm->roles_.push_back(r);

        int ret = tm->roles_.back()->init(role_client);
        if (ret != 0) {
            printf("client init error");
            return;
        }

        ret = tm->roles_.back()->create_client();
        if (ret != 0) {
            printf("client create error");
            return;
        }
        index++;
    }

    if (index  >= tm->client_num_) {

        printf("all robot login success...\n");

        uv_timer_stop(handle);
        tm->send_start_ = get_ms_time();

        for (auto client : tm->roles_) {
            client->start_client_send(1);
        }
    }
}

void  test_mgr::print_stress_test_result() {
    if (instance_ == nullptr) return;

    double send_freq = (1000.0 * test_mgr::instance_->msg_send_) / (test_mgr::instance_->send_end_ - test_mgr::instance_->send_start_);
    double recv_aveg_delay = test_mgr::instance_->recv_cost_ * 1.0 / test_mgr::instance_->msg_recv_;
    printf("robot_num:%d msg_total:%ld msg_send:%ld msg_recv:%ld send_freq:%.2lf QPS:%.2lf recv_aveg_delay:%.5lf \n", instance_->client_num_, instance_->msg_total_, instance_->msg_send_, instance_->msg_recv_, send_freq, instance_->QPS_, recv_aveg_delay);

    printf("stress test ending!!! Bye Bye!\n");
}
